package com.alquimia.truco.dominio.modelo;

import java.util.*;

/**
 * Created by Ivo on 29/05/2014.
 */
class Partido {

    private PartidoId partidoId;
    private final Map<JugadorId, Jugador> jugadores = new HashMap<>();
    private Ronda rondaActual;
    private Modalidad modalidad;

    public Partido(PartidoId aPartidoId, Modalidad aModalidad) {
        this();

        setPartidoId(aPartidoId);
        setModalidad(aModalidad);
    }

    private Partido() {
        super();
    }

    private void iniciarPartida() {

        setRondaActual(new Ronda(this.jugadores()));
        this.rondaActual().nuevaRonda();
    }

    public void nuevaJugada(JugadorId aJugadorId, Accion aEstadoAccion) {
        rondaActual().nuevaJugada(aJugadorId, aEstadoAccion);

        if (this.hayGanador()) {

        }
    }

    private boolean hayGanador() {
        return this.jugadores().values().stream().anyMatch(e -> e.puntos() >= this.modalidad().puntosNecesarios());
    }

    public void anotarJugador(Jugador aJugador) {

        if (aJugador == null)
            throw new NullPointerException("El jugador no puede ser nulo.");
        if (estanTodosLosJugadores())
            throw new IllegalStateException("La partida esta completa.");
        if (estaAnotado(aJugador))
            throw new IllegalStateException("El jugador ya se encuentra inscripto.");

        this.jugadores().put(aJugador.jugadorId(), aJugador);

        if (estanTodosLosJugadores()) {
            iniciarPartida();
        }
    }

    public void anotarJugadores(Jugador aJugadorUno, Jugador aJugadorDos) {

        if (aJugadorUno == null || aJugadorDos == null)
            throw new NullPointerException("Los jugadores no pueden ser nulos.");
        if (!noHayJugadoresAnotados())
            throw new IllegalStateException("No hay lugar para dos jugadores.");

        this.jugadores().put(aJugadorUno.jugadorId(), aJugadorUno);
        this.jugadores().put(aJugadorUno.jugadorId(), aJugadorDos);

        if (estanTodosLosJugadores()) {
            iniciarPartida();
        }

    }

    public boolean estaAnotado(Jugador aJugador) {
        return this.jugadores().containsKey(aJugador.jugadorId());
    }

    private boolean noHayJugadoresAnotados() {
        return this.jugadores().size() == 0;
    }

    private boolean estanTodosLosJugadores() {
        return this.jugadores().size() == 2;
    }

    @Override
    public int hashCode() {
        return this.partidoId().hashCode();
    }

    @Override
    public boolean equals(Object aObject) {

        boolean equalObjects = false;
        if (aObject != null && aObject.getClass() == this.getClass()) {
            Partido partido = (Partido) aObject;
            equalObjects = partido.partidoId().equals(this.partidoId());
        }

        return equalObjects;
    }

    @Override
    public String toString() {
        return this.getClass().getSimpleName() + "[partidoId=" + partidoId() + "]";
    }

    public PartidoId partidoId() {
        return this.partidoId;
    }

    public Map<JugadorId, Jugador> jugadores() {
        return this.jugadores;
    }

    private void setPartidoId(PartidoId aPartidoId) {
        if (aPartidoId == null)
            throw new NullPointerException("El partido id no debe ser nulo.");
        this.partidoId = aPartidoId;
    }

    protected Ronda rondaActual() {
        return this.rondaActual;
    }

    private void setRondaActual(Ronda aRondaActual) {
        this.rondaActual = aRondaActual;
    }

    public Modalidad modalidad() {
        return this.modalidad;
    }

    private void setModalidad(Modalidad aModalidad) {
        this.modalidad = aModalidad;
    }

}
